using UnityEngine;

public class SingleTableTennis : MonoBehaviour
{
	public struct ShotParams
	{
		public int touchesInTable;

		public bool isServeShot;
	}

	public class TableTennisScore
	{
		public int points;

		public int totalPoints;

		public int games;
	}

	protected int pointsToWin = 11;

	protected int gamesToWin = 1;

	public TableTennisScore[] score = new TableTennisScore[2]
	{
		new TableTennisScore(),
		new TableTennisScore()
	};

	protected MatchController match;

	protected ShotParams currentShot;

	protected MatchUI ui;

	public Ball ball
	{
		get
		{
			return match.ball;
		}
	}

	public PlayerBase servingPlayer { get; protected set; }

	public int numShotsInPoint { get; protected set; }

	public bool isGameWon
	{
		get
		{
			return Mathf.Max(score[0].games, score[1].games) >= gamesToWin;
		}
	}

	public PlayerBase playerThatWon
	{
		get
		{
			if (!isGameWon)
			{
				return null;
			}
			if (score[0].games > score[1].games)
			{
				return match.GetPlayer(0);
			}
			return match.GetPlayer(1);
		}
	}

	public int GetTotalPointsDifference()
	{
		return score[0].points - score[1].points;
	}

	public int GetScoreDifference(int playerTag)
	{
		return score[playerTag].points - score[(playerTag + 1) % 2].points;
	}

	public void Init(MatchController match, MatchUI ui, int numPointsToWinGame, int numGamesToWinMatch)
	{
		pointsToWin = numPointsToWinGame;
		gamesToWin = numGamesToWinMatch;
		this.match = match;
		this.ui = ui;
	}

	public void SetServingPlayer(PlayerBase player)
	{
		servingPlayer = player;
	}

	public void StartMatch(int activePlayer = 0)
	{
		servingPlayer = match.GetPlayer(activePlayer);
		StartServe();
	}

	private void StartServe()
	{
		numShotsInPoint = 0;
		match.StartServe(servingPlayer);
	}

	public bool OnPlayerHitBall(PlayerBase player)
	{
		if (!ball.isBallInGame && !ball.flightPlan.isServeBall)
		{
			return false;
		}
		numShotsInPoint++;
		ball.isBallInGame = true;
		ShotParams shotParams = currentShot;
		currentShot = default(ShotParams);
		currentShot.isServeShot = ball.flightPlan.isServeBall;
		if (currentShot.isServeShot)
		{
			return true;
		}
		return true;
	}

	public void OnBallHitObject(Vector3 pos, HitObjectTag hitObjectTag)
	{
		if (!ball.isBallInGame)
		{
			return;
		}
		if (hitObjectTag == HitObjectTag.Table)
		{
			currentShot.touchesInTable++;
		}
		int num = ((!currentShot.isServeShot) ? 1 : 2);
		if (currentShot.touchesInTable > num)
		{
			AwardPointTo(ball.flightPlan.playerThatHitBall, false);
		}
		else if (hitObjectTag == HitObjectTag.Floor)
		{
			if (currentShot.touchesInTable == num)
			{
				AwardPointTo(ball.flightPlan.playerThatHitBall, false);
			}
			else
			{
				AwardPointTo(match.Other(ball.flightPlan.playerThatHitBall), false);
			}
		}
	}

	private void AwardPointTo(PlayerBase player, bool isTimeOut)
	{
		ball.isBallInGame = false;
		score[player.teamTag].points++;
		score[player.teamTag].totalPoints++;
		int num = score[0].points + score[1].points;
		int num2 = Mathf.Min(score[0].points, score[1].points);
		int num3 = Mathf.Max(score[0].points, score[1].points);
		bool flag = num3 - num2 >= 2 && num3 >= pointsToWin;
		if (num % 2 == 0 || num2 >= pointsToWin - 1)
		{
			servingPlayer = match.Other(servingPlayer);
		}
		if (flag)
		{
			int num4 = ((score[0].points <= score[1].points) ? 1 : 0);
			score[num4].games++;
			for (int i = 0; i < score.Length; i++)
			{
				score[i].points = 0;
			}
		}
		AwardPointParams awardPointParams = default(AwardPointParams);
		awardPointParams.isSetWon = flag;
		awardPointParams.playerThatWonPoint = player;
		awardPointParams.isTimeOut = isTimeOut;
		match.AwardPoint(awardPointParams);
	}

	public void SyncGameScore(MGameScoreSync scoreSync)
	{
		score[0].points = scoreSync.p2Points;
		score[0].games = scoreSync.p2Games;
		score[1].points = scoreSync.p1Points;
		score[1].games = scoreSync.p1Games;
		servingPlayer = match.GetPlayer(scoreSync.servingPlayerTag);
	}

	public MGameScoreSync ToGameScoreSync(AwardPointParams lastPoint)
	{
		MGameScoreSync result = default(MGameScoreSync);
		result.p1Points = score[0].points;
		result.p1Games = score[0].games;
		result.p2Points = score[1].points;
		result.p2Games = score[1].games;
		result.isSetWon = lastPoint.isSetWon;
		result.servingPlayerTag = servingPlayer.teamTag;
		result.isTimeOut = lastPoint.isTimeOut;
		if (lastPoint.playerThatWonPoint != null)
		{
			result.playerTagThatWonPoint = lastPoint.playerThatWonPoint.teamTag;
		}
		else
		{
			result.playerTagThatWonPoint = -1;
		}
		return result;
	}

	public void ContinueFromLastPoint(AwardPointParams lastPoint)
	{
		if (lastPoint.isSetWon)
		{
			ui.UpdateSets(score[0].games, score[1].games);
		}
		for (int i = 0; i < score.Length; i++)
		{
			ui.SetScores(i, score[i].points.ToString());
		}
		if (isGameWon)
		{
			bool isPlayerWinner = playerThatWon as HumanPlayer != null;
			match.OnGameWon(isPlayerWinner);
		}
		else
		{
			this.WaitAndExecute(1f, delegate
			{
				StartServe();
			});
		}
	}

	public void OnTimeOut()
	{
		AwardPointTo(match.Other(servingPlayer), true);
	}
}
